using System;
using System.Net;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Web.Services.Protocols;

using Microsoft.Crm.Sdk.Proxy;

namespace CRM_Perf_BenchMark
{
    [TestClass]
    public class BulkDeleteUnitTests
    {
        CRMEntity m_user;
        string m_userName = string.Empty;
        string m_domain = string.Empty;
        string m_password = string.Empty;
        string m_organization = string.Empty;
        string m_crmticket = string.Empty;
        NetworkCredential m_nc = null;
        CrmService Proxy = null;
        string m_CrmServer = string.Empty;
        string m_ApiServer = string.Empty;

        // Need this public property for webservice so that we do not use the default credential
        public System.Net.NetworkCredential NetworkCredential
        {
            get
            {
                return m_nc;
            }
            set
            {
                m_nc = value;
            }
        }

        private static string resultDir = Directory.GetDirectoryRoot(Directory.GetCurrentDirectory()) + @"PerfResult";

        public BulkDeleteUnitTests()
        {
           
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        [ClassInitialize()]
        public static void ClassInitialize(TestContext testContext)
        {
            //this is the directory where all perf results are stored
            string perfResultDir = Directory.GetDirectoryRoot(Directory.GetCurrentDirectory()) + @"PerfResult";
            if (!Directory.Exists(perfResultDir))
                Directory.CreateDirectory(perfResultDir);
        }

        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void TestInitialize()
        {
            m_user = EntityManager.Instance.GetNextUser();
            Proxy = new CrmService();

            string[] splits = m_user["domainname"].Split(new char[] { '\\' }, 2, StringSplitOptions.RemoveEmptyEntries);
            if (splits.Length > 1)
            {
                m_domain = splits[0];
                m_userName = splits[1];
            }

            m_CrmServer = m_user["CrmServer"];
            m_ApiServer = m_user["ApiServer"];
            m_password = m_user["userpassword"];
            m_organization = m_user["organizationname"];

            if (!SetupWebService())
            {
                System.Diagnostics.Trace.WriteLine("Setup Web Service did not succeed");
            }
        }

        public bool SetupWebService()
        {
            Proxy.Url = m_ApiServer + "/MSCRMServices/2007/CrmService.asmx";

            Proxy.UnsafeAuthenticatedConnectionSharing = true;
            m_nc = new NetworkCredential(m_userName, m_password, m_domain);
            Proxy.ConnectionGroupName = m_domain + "\\" + m_userName;
            Proxy.Credentials = m_nc;

            CrmAuthenticationToken token = new CrmAuthenticationToken();
            token.OrganizationName = m_organization;
            
            token.AuthenticationType = AuthenticationType.AD;
            
            Proxy.CrmAuthenticationTokenValue = token;
            return true;
        }

        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void TestCleanup()
        {
            EntityManager.Instance.FreeEntity(m_user);
            Proxy = null;
        }

        #endregion

        #region Individual Test Cases


        [TestMethod()]
        public void DMUnitTest_BulkDelete_LeadsFromQuery()
        {
            DeleteLeadsFromQuery(1000);
        }

        
        #endregion

        #region Test Case Registration

        private void DeleteLeadsFromQuery(int count)
        {
            QueryExpression query = new QueryExpression();
            query.EntityName = "lead";
            FilterExpression fe = new FilterExpression(); 
            ConditionExpression conditionStatus = new ConditionExpression();
            conditionStatus.AttributeName = "statuscode";
            conditionStatus.Operator = ConditionOperator.Equal;
            conditionStatus.Values = new object[] { 1 };

            ConditionExpression conditionFirstName = new ConditionExpression();
            conditionFirstName.AttributeName = "firstname";
            conditionFirstName.Operator = ConditionOperator.Equal;
            conditionFirstName.Values = new object[] { "First Name Delete" };

            ConditionExpression conditionLastName = new ConditionExpression();
            conditionLastName.AttributeName = "lastname";
            conditionLastName.Operator = ConditionOperator.Equal;
            conditionLastName.Values = new object[] { "Last Name Delete" };

            ConditionExpression conditionMiddleName = new ConditionExpression();
            conditionMiddleName.AttributeName = "middlename";
            conditionMiddleName.Operator = ConditionOperator.Equal;
            conditionMiddleName.Values = new object[] { "Middle Name Delete" };

            FilterExpression f1 = new FilterExpression();
            f1.Conditions = new ConditionExpression[] { conditionFirstName, conditionLastName };
            f1.FilterOperator = LogicalOperator.And;

            FilterExpression f2 = new FilterExpression();
            f2.Conditions = new ConditionExpression[] { conditionMiddleName };
            f2.Filters = new FilterExpression[] { f1 };
            f2.FilterOperator = LogicalOperator.Or;

            FilterExpression f3 = new FilterExpression();
            f3.Conditions = new ConditionExpression[] { conditionStatus};
            f3.Filters = new FilterExpression[] { f2 };
            f3.FilterOperator = LogicalOperator.And;
            
            query.Criteria = f3;
            ColumnSetBase cs = new AllColumns();
            query.ColumnSet = cs;
          
            
            lead ld = new lead();
            ld.firstname = "First Name Delete";
            ld.lastname = "Last Name Delete";
            ld.subject = "subject";
            ld.companyname = "Microsoft";

      
            for (int i = 0; i < count; i++)
            {
                try
                {
                    Proxy.Create(ld);
                }
                catch (Exception e)
                {
                    System.Diagnostics.Trace.WriteLine("Entity creation failed..." + e.Message);
                    throw e;
                }
            }

            DateTime startTime = DateTime.Now;
            string SummaryFile = resultDir + @"\BulkDeleteLeads_" + startTime.Ticks.ToString() + ".log";

            Guid bulkDeleteJobId = BulkDeleteWithNoRecurrence(new QueryExpression[] { query }, "Bulk Delete Leads With Conditions", false, new Guid[] { Guid.Empty }, new Guid[] { Guid.Empty });

            lock (typeof(StreamWriter))
            {
                StreamWriter logWriter = new StreamWriter(SummaryFile);
                logWriter.WriteLine("Logging test reult for Bulk Delete ...");
                logWriter.WriteLine("--------------------------------------");
                logWriter.WriteLine("Bulk Delete Id for this test is " + bulkDeleteJobId.ToString());
                logWriter.WriteLine("Test started at " + startTime);
                logWriter.Flush();
                logWriter.Close();
            }
            
        }

        #endregion

        #region Test Case Helper Methodes

        
        /// <summary>
        /// Calls bulk-detect-duplicates with E-mail confirmation for the query exp passed
        /// </summary>
        /// <param name="query">Query exp for which bulk detect duplicates is desired</param>
        /// <param name="toRecipients">users to whom mail is to be sent</param>
        /// <param name="ccRecipients">users to whom mail is be 'cc-ed'</param>
        /// <param name="templateID">template to be used for sending mail</param>
        /// <returns>Job id of the bulk de-detect job</returns>
        private Guid BulkDeleteWithNoRecurrence(QueryExpression[] query, string jobName, bool sendEmailNotification, Guid[] toRecipients, Guid[] ccRecipients)
        {
            BulkDeleteRequest request = new BulkDeleteRequest();
            request.QuerySet = query;
            request.JobName = jobName;
            request.SendEmailNotification = sendEmailNotification;
            request.ToRecipients = toRecipients;
            request.CCRecipients = ccRecipients;
            request.RecurrencePattern = string.Empty;
            request.StartDateTime = new CrmDateTime(DateTime.Now.ToString());
          
            BulkDeleteResponse response = (BulkDeleteResponse)Proxy.Execute(request);
      
            return response.JobId;
        }

         #endregion
    }

}
